# @Time    : 2022/10/7 9:07
# @Author  : 南黎
# @FileName: 2.2(错误对比版本)神经网络模型实现波士顿房价预测模型可视化.py
import time

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.neural_network import  MLPRegressor
import matplotlib.pyplot as plt

orgin_data = pd.read_csv("boston.csv")
# print(orgin_data)

# a.数据进行归一化
max_abs_scaler = preprocessing.MaxAbsScaler()  # 注册一个预处理对象
sizeOfOne_data = max_abs_scaler.fit_transform(orgin_data)  # fit_transform(X[, y])	适合数据，然后转换它。
# print(sizeOfOne_data)

# b.理论上按照一般流程来讲这里最好还是要划分训练集和测试集
X = sizeOfOne_data[:, 0:13]  # 13个特征x
Y = sizeOfOne_data[:, 13:]  # 一个标签y #ravel()方法将数组维度拉成一维数组

# PS：如果不将数组维度拉成一维数组，会出现警告信息，但是不影响运行，这意味着规范书写
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
# train_test_split是交叉验证中常用的函数，功能是从样本中随机的按比例选取train data和testdata
# train_data：所要划分的样本特征集
# train_target：所要划分的样本结果
# test_size：样本占比，如果是整数的话就是样本的数量,0.2表示20%的测试集
# random_state：是随机数的种子。

# b.创建神经网络回归器
def creat_train(hidden_layer_sizes):
    time_begin=time.time()
    mpl = MLPRegressor(hidden_layer_sizes=(5, 2, 2), activation='relu', solver='lbfgs',max_iter=300)
    # 1. hidden_layer_sizes :例如hidden_layer_sizes=(5, 2, 2)，表示有3层隐藏层，第一层隐藏层有5个神经元，第二层有2个神经元,第三层也有2个神经元
    #
    # 2. activation :激活函数, {‘identity’, ‘logistic’, ‘tanh’, ‘relu’}, 默认relu
    #
    # - identity：f(x) = x
    #
    # - logistic：其实就是sigmod,f(x) = 1 / (1 + exp(-x)).
    #
    # - tanh：f(x) = tanh(x).
    #
    # - relu：f(x) = max(0, x)
    #
    # 3. solver：  {‘lbfgs’, ‘sgd’, ‘adam’},, 默认adam，用来优化权重
    #
    # - lbfgs：quasi-Newton方法的优化器
    #
    # - sgd：随机梯度下降
    #
    # - adam： Kingma, Diederik, and Jimmy Ba提出的机遇随机梯度的优化器
    #
    # 注意：默认solver ‘adam’在相对较大的数据集上效果比较好（几千个样本或者更多），对小数据集来说，lbfgs收敛更快效果也更好。
    #
    # 4. alpha :float,可选的，默认0.0001,正则化项参数
    #
    # 5. batch_size : int , 可选的，默认’auto’,随机优化的minibatches的大小batch_size=min(200,n_samples)，如果solver是’lbfgs’，分类器将不使用minibatch
    #
    # 6. learning_rate :学习率,用于权重更新,只有当solver为’sgd’时使用，{‘constant’，’invscaling’, ‘adaptive’},默认constant

    # 7. max_iter : 迭代次数，int, optional, default 200
    # 训练神经网络模型
    mpl.fit(X_train, Y_train.ravel())
    # 打印模型预测评分
    print('Score:\n', mpl.score(X_test, Y_test))
    time_cost = time.time()-time_begin
    print('time_cost:\n', time_cost)
    print("--------------")
    # 绘制可视化图
    plt.rcParams["font.sans-serif"] = ["SimHei"]  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    plt.title("实际房价与预测房价")
    plt.xlabel("数据序号")
    plt.ylabel("房价")
    predict_Y=mpl.predict(X)#使用MLP进行预测
    # print(predict_Y)
    # print(Y)
    plt.plot([x for x in range(1,len(X)+1)], predict_Y, label='预测房间')
    plt.plot([x for x in range(1,len(X)+1)], Y, label='实际房价')
    # 绘制标签
    plt.legend(['预测房间', '实际房价'], loc=2, fontsize=10)

    plt.savefig("2/2.2 实际房价与预测房价.png")
    plt.show()


creat_train((5, 2, 2))
